home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C="$Id: if.c,v 1.21 1993/10/29 02:00:17 ppessi Exp $";
- /*
- * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
- * Helsinki University of Technology, Finland.
- * All rights reserved.
- *
- * if.c --- Generic Network Interface Routines
- *
- * Last modified: Thu Oct 28 22:38:01 1993 ppessi
- *
- * HISTORY
- * $Log: if.c,v $
- * Revision 1.21 1993/10/29 02:00:17 ppessi
- * Added SIOCGARPT ioctl.
- *
- * Revision 1.21 1993/10/29 02:00:17 ppessi
- * Added SIOCGARPT ioctl.
- *
- * Revision 1.20 1993/09/19 21:14:18 jraja
- * Fixed a bug with '/' placement in ifconf().
- *
- * Revision 1.19 1993/09/09 23:45:36 ppessi
- * Changed the interface name format returned by SIOCGIFCONF.
- *
- * Revision 1.18 1993/06/04 11:16:15 jraja
- * Fixes for first public release.
- *
- * Revision 1.17 1993/05/16 21:09:43 ppessi
- * RCS version changed.
- *
- * Revision 1.16 1993/04/24 23:42:37 jraja
- * Removed few #ifdef AMITCP's.
- *
- * Revision 1.15 93/04/24 23:20:01 23:20:01 jraja (Jarno Tapio Rajahalme)
- * Removed #ifdef NOALIGN, now using straight structure copies.
- *
- * Revision 1.14 93/04/19 02:09:58 02:09:58 ppessi (Pekka Pessi)
- * arpioctl() declared here instead of protos file.
- *
- * Revision 1.13 93/04/13 22:19:02 22:19:02 jraja (Jarno Tapio Rajahalme)
- * Added casts to the pr_usrreq calls to comply with the prototype.
- *
- * Revision 1.12 93/04/11 22:20:06 22:20:06 jraja (Jarno Tapio Rajahalme)
- * Removed unnecessary casts from function pointers, Changed ellipses to
- * prototypes.
- *
- * Revision 1.11 93/04/05 17:45:06 17:45:06 jraja (Jarno Tapio Rajahalme)
- * Changed spl storage variables to spl_t.
- * Changed every .c file to use conf.h.
- *
- * Revision 1.10 93/03/19 14:30:32 14:30:32 too (Tomi Ollila)
- * Code changes at night 17-18 March 1993
- *
- * Revision 1.9 93/03/12 23:54:16 23:54:16 ppessi (Pekka Pessi)
- * Cancelled if_down() kludge.
- *
- * Revision 1.1 93/03/12 05:26:56 05:26:56 ppessi (Pekka Pessi)
- * pulled if_down() to if_sana.c; Final Kludge to sana_up/down()
- * #ifdef'ed if_dl.h and if_types.h from includes
- *
- * Revision 1.8 93/03/09 17:56:17 17:56:17 ppessi (Pekka Pessi)
- * Fixed bug with unit number conversion.
- *
- * Revision 1.1 93/03/09 17:55:36 17:55:36 ppessi (Pekka Pessi)
- * Initial revision
- *
- * Revision 1.7 93/03/05 19:50:37 19:50:37 jraja (Jarno Tapio Rajahalme)
- * Fixed includes (again).
- *
- * Revision 1.6 93/03/05 03:11:56 03:11:56 ppessi (Pekka Pessi)
- * Compiles with SASC. Initial test version
- *
- * Revision 1.5 93/02/28 21:34:42 21:34:42 ppessi (Pekka Pessi)
- * Changed device name semantics (now devs:foo/xx/00 instead of xx00)
- * Kludged IFF_UP passing to if_ioctl() call.
- *
- * Revision 1.4 93/02/24 10:22:52 10:22:52 jraja (Jarno Tapio Rajahalme)
- * Fixed timeout().
- *
- * Revision 1.3 93/02/19 15:38:07 15:38:07 jraja (Jarno Tapio Rajahalme)
- * Changed ifioctl's proc argument to SocketBase.
- *
- * Revision 1.2 92/11/20 14:42:42 14:42:42 jraja (Jarno Tapio Rajahalme)
- * added #ifndef AMITCP's to get this compile somehow
- *
- * Revision 1.1 92/11/20 13:31:58 13:31:58 jraja (Jarno Tapio Rajahalme)
- * Initial revision
- */
-
- /*
- * Mach Operating System
- * Copyright (c) 1992 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- * HISTORY
- * Log: if.c,v
- * Revision 2.1 92/04/21 17:13:56 rwd
- * BSDSS
- *
- *
- */
-
- /*
- * Copyright (c) 1980, 1986 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)if.c 7.14 (Berkeley) 4/20/91
- */
-
- #include <conf.h>
-
- #include <sys/param.h>
- #include <sys/malloc.h>
- #include <sys/mbuf.h>
- #include <sys/systm.h>
- #include <sys/socket.h>
- #include <sys/socketvar.h>
- #include <sys/protosw.h>
- #include <sys/kernel.h>
- #include <sys/ioctl.h>
- #include <sys/synch.h>
-
- #include <net/if.h>
- #include <net/if_dl.h>
-
- #include <net/if_protos.h>
- #include <kern/uipc_domain_protos.h>
-
- static char *sprint_d(u_int n, char *buf, int buflen);
- int ifqmaxlen = IFQ_MAXLEN;
-
- struct ifnet *ifnet = NULL;
-
- /*
- * Network interface utility routines.
- *
- * Routines with ifa_ifwith* names take sockaddr *'s as
- * parameters.
- */
-
- void ifinit(void)
- {
- register struct ifnet *ifp;
-
- for (ifp = ifnet; ifp; ifp = ifp->if_next)
- if (ifp->if_snd.ifq_maxlen == 0)
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
- if_slowtimo();
- }
-
- #ifdef vax
- /*
- * Call each interface on a Unibus reset.
- */
- ifubareset(uban)
- int uban;
- {
- register struct ifnet *ifp;
-
- for (ifp = ifnet; ifp; ifp = ifp->if_next)
- if (ifp->if_reset)
- (*ifp->if_reset)(ifp->if_unit, uban);
- }
- #endif
-
- int if_index = 0;
- struct ifaddr **ifnet_addrs;
- static char *sprint_d();
-
- /*
- * Attach an interface to the
- * list of "active" interfaces.
- */
- void
- if_attach(ifp)
- struct ifnet *ifp;
- {
- unsigned socksize, ifasize;
- int namelen, unitlen;
- char workbuf[12], *unitname;
- register struct ifnet **p = &ifnet;
- register struct sockaddr_dl *sdl;
- register struct ifaddr *ifa;
- static int if_indexlim = 8;
-
- while (*p)
- p = &((*p)->if_next);
- *p = ifp;
- ifp->if_index = ++if_index;
- if (ifnet_addrs == 0 || if_index >= if_indexlim) {
- unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
- struct ifaddr **q = (struct ifaddr **)
- bsd_malloc(n, M_IFADDR, M_WAITOK);
- if (ifnet_addrs) {
- aligned_bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
- bsd_free((caddr_t)ifnet_addrs, M_IFADDR);
- }
- ifnet_addrs = q;
- }
- /*
- * create a Link Level name for this device
- */
- #ifdef AMITCP
- /* Exec device name can contain digits, workaround with slash */
- unitname = sprint_d((u_int)ifp->if_unit,
- workbuf + 1,
- sizeof(workbuf) - 1);
- *--unitname = '/';
- #else
- unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
- #endif
- namelen = strlen(ifp->if_name);
- unitlen = strlen(unitname);
- #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
- socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
- unitlen + namelen + ifp->if_addrlen;
- #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
- socksize = ROUNDUP(socksize);
- if (socksize < sizeof(*sdl))
- socksize = sizeof(*sdl);
- ifasize = sizeof(*ifa) + 2 * socksize;
- ifa = (struct ifaddr *)bsd_malloc(ifasize, M_IFADDR, M_WAITOK);
- if (ifa == 0)
- return;
- ifnet_addrs[if_index - 1] = ifa;
- aligned_bzero((caddr_t)ifa, ifasize);
- sdl = (struct sockaddr_dl *)(ifa + 1);
- ifa->ifa_addr = (struct sockaddr *)sdl;
- ifa->ifa_ifp = ifp;
- sdl->sdl_len = socksize;
- sdl->sdl_family = AF_LINK;
- bcopy(ifp->if_name, sdl->sdl_data, namelen);
- bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
- sdl->sdl_nlen = (namelen += unitlen);
- sdl->sdl_index = ifp->if_index;
- sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
- ifa->ifa_netmask = (struct sockaddr *)sdl;
- sdl->sdl_len = socksize - ifp->if_addrlen;
- while (namelen != 0)
- sdl->sdl_data[--namelen] = (char)0xff;
- ifa->ifa_next = ifp->if_addrlist;
- ifa->ifa_rtrequest = link_rtrequest;
- ifp->if_addrlist = ifa;
- }
- /*
- * Locate an interface based on a complete address.
- */
- /*ARGSUSED*/
- struct ifaddr *
- ifa_ifwithaddr(addr)
- register struct sockaddr *addr;
- {
- register struct ifnet *ifp;
- register struct ifaddr *ifa;
-
- #define equal(a1, a2) \
- (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
- for (ifp = ifnet; ifp; ifp = ifp->if_next)
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != addr->sa_family)
- continue;
- if (equal(addr, ifa->ifa_addr))
- return (ifa);
- if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
- equal(ifa->ifa_broadaddr, addr))
- return (ifa);
- }
- return ((struct ifaddr *)0);
- }
- /*
- * Locate the point to point interface with a given destination address.
- */
- /*ARGSUSED*/
- struct ifaddr *
- ifa_ifwithdstaddr(addr)
- register struct sockaddr *addr;
- {
- register struct ifnet *ifp;
- register struct ifaddr *ifa;
-
- for (ifp = ifnet; ifp; ifp = ifp->if_next)
- if (ifp->if_flags & IFF_POINTOPOINT)
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != addr->sa_family)
- continue;
- if (equal(addr, ifa->ifa_dstaddr))
- return (ifa);
- }
- return ((struct ifaddr *)0);
- }
-
- /*
- * Find an interface on a specific network. If many, choice
- * is first found.
- */
- struct ifaddr *
- ifa_ifwithnet(addr)
- struct sockaddr *addr;
- {
- register struct ifnet *ifp;
- register struct ifaddr *ifa;
- u_int af = addr->sa_family;
-
- if (af >= AF_MAX)
- return (0);
- if (af == AF_LINK) {
- register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
- if (sdl->sdl_index && sdl->sdl_index <= if_index)
- return (ifnet_addrs[sdl->sdl_index - 1]);
- }
- for (ifp = ifnet; ifp; ifp = ifp->if_next)
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
- register char *cp, *cp2, *cp3;
- register char *cplim;
- if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
- continue;
- cp = addr->sa_data;
- cp2 = ifa->ifa_addr->sa_data;
- cp3 = ifa->ifa_netmask->sa_data;
- cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
- for (; cp3 < cplim; cp3++)
- if ((*cp++ ^ *cp2++) & *cp3)
- break;
- if (cp3 == cplim)
- return (ifa);
- }
- return ((struct ifaddr *)0);
- }
-
- /*
- * Find an interface using a specific address family
- */
- struct ifaddr *
- ifa_ifwithaf(af)
- register int af;
- {
- register struct ifnet *ifp;
- register struct ifaddr *ifa;
-
- for (ifp = ifnet; ifp; ifp = ifp->if_next)
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
- if (ifa->ifa_addr->sa_family == af)
- return (ifa);
- return ((struct ifaddr *)0);
- }
-
- /*
- * Find an interface address specific to an interface best matching
- * a given address.
- */
- struct ifaddr *
- ifaof_ifpforaddr(addr, ifp)
- struct sockaddr *addr;
- register struct ifnet *ifp;
- {
- register struct ifaddr *ifa;
- register char *cp, *cp2, *cp3;
- register char *cplim;
- struct ifaddr *ifa_maybe = 0;
- u_int af = addr->sa_family;
-
- if (af >= AF_MAX)
- return (0);
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != af)
- continue;
- ifa_maybe = ifa;
- if (ifa->ifa_netmask == 0) {
- if (equal(addr, ifa->ifa_addr) ||
- (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
- return (ifa);
- continue;
- }
- cp = addr->sa_data;
- cp2 = ifa->ifa_addr->sa_data;
- cp3 = ifa->ifa_netmask->sa_data;
- cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
- for (; cp3 < cplim; cp3++)
- if ((*cp++ ^ *cp2++) & *cp3)
- break;
- if (cp3 == cplim)
- return (ifa);
- }
- return (ifa_maybe);
- }
- #include <net/route.h>
- /*
- * Default action when installing a route with a Link Level gateway.
- * Lookup an appropriate real ifa to point to.
- * This should be moved to /sys/net/link.c eventually.
- */
- void
- link_rtrequest(int cmd, register struct rtentry *rt, struct sockaddr *sa)
- {
- register struct ifaddr *ifa;
- struct sockaddr *dst;
- struct ifnet *ifp;
-
- if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
- ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
- return;
- if (ifa = ifaof_ifpforaddr(dst, ifp)) {
- rt->rt_ifa = ifa;
- if (ifa->ifa_rtrequest &&
- ifa->ifa_rtrequest != link_rtrequest)
- ifa->ifa_rtrequest(cmd, rt, sa);
- }
- }
-
- /*
- * Mark an interface down and notify protocols of
- * the transition.
- * NOTE: must be called at splnet or eqivalent.
- */
- void
- if_down(ifp)
- register struct ifnet *ifp;
- {
- register struct ifaddr *ifa;
-
- ifp->if_flags &= ~IFF_UP;
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
- pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
- if_qflush(&ifp->if_snd);
- }
-
- /*
- * Flush an interface queue.
- */
- void
- if_qflush(ifq)
- register struct ifqueue *ifq;
- {
- register struct mbuf *m, *n;
-
- n = ifq->ifq_head;
- while (m = n) {
- n = m->m_act;
- m_freem(m);
- }
- ifq->ifq_head = 0;
- ifq->ifq_tail = 0;
- ifq->ifq_len = 0;
- }
-
- /*
- * Handle interface watchdog timer routines. Called
- * from softclock, we decrement timers (if set) and
- * call the appropriate interface routine on expiration.
- */
- void
- if_slowtimo()
- {
- /*
- * This routine is disabled since there are
- * no timeouts in our network interfaces
- */
- #ifndef AMITCP
- register struct ifnet *ifp;
- spl_t s = splimp();
-
- for (ifp = ifnet; ifp; ifp = ifp->if_next) {
- if (ifp->if_timer == 0 || --ifp->if_timer)
- continue;
- if (ifp->if_watchdog)
- (*ifp->if_watchdog)(ifp->if_unit);
- }
- splx(s);
- #ifndef AMITCP
- /*
- * Timeouts are scheduled from amiga_time.c in AmiTCP/IP.
- */
- timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
- #endif
- #endif
- }
-
- /*
- * Map interface name to
- * interface structure pointer.
- */
- struct ifnet *
- ifunit(name)
- register char *name;
- {
- register char *cp;
- register struct ifnet *ifp;
- int unit;
- unsigned len;
- char *ep, c;
-
- #ifdef AMITCP
- /* AmigaTCP/IP uses the slash as unit number separator
- * because Exec device name may contain digits.
- */
- char *up;
- cp = ep = name - 1;
- /* Find pathpart */
- for (up = name; *up; up++)
- if (*up == '/' || *up == ':') {
- cp = ep;
- ep = up;
- }
- /* Name is too long, or there is no unit number */
- if (up >= cp + IFNAMSIZ || cp == ep)
- return ((struct ifnet *)0);
- cp++;
- /*
- * cp points first char in device name,
- * ep to unit number separator ('/')
- * and up to NUL ('\0') at the end of string
- */
- len = ep - cp;
- c = *ep;
- *ep = '\0'; /* sentinel */
- for (unit = 0, up--; *up >= '0' && *up <= '9'; up--)
- unit = unit * 10 + *up - '0';
- *ep = c;
- if (up != ep) {
- return NULL;
- }
- /* Pathpart is not included in search */
- for (ifp = ifnet; ifp; ifp = ifp->if_next) {
- if (bcmp(ifp->if_name, cp, len))
- continue;
- if (unit == ifp->if_unit)
- break;
- }
- #else
- for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
- if (*cp >= '0' && *cp <= '9')
- break;
- if (*cp == '\0' || cp == name + IFNAMSIZ)
- return ((struct ifnet *)0);
- /*
- * Save first char of unit, and pointer to it,
- * so we can put a null there to avoid matching
- * initial substrings of interface names.
- */
- len = cp - name + 1;
- c = *cp;
- ep = cp;
- for (unit = 0; *cp >= '0' && *cp <= '9'; )
- unit = unit * 10 + *cp++ - '0';
- *ep = 0;
-
- for (ifp = ifnet; ifp; ifp = ifp->if_next) {
- if (bcmp(ifp->if_name, name, len))
- continue;
- if (unit == ifp->if_unit)
- break;
- }
- *ep = c;
- #endif
- {
- extern struct ifnet *iface_find(char *);
- if (ifp == 0)
- ifp = iface_find(name);
- }
- return (ifp);
- }
-
- /*
- * Interface ioctls.
- */
- int
- ifioctl(so, cmd, data)
- struct socket *so;
- int cmd;
- caddr_t data;
- {
- register struct ifnet *ifp;
- register struct ifreq *ifr;
- #ifndef AMITCP
- int error;
- #endif
- extern int arpioctl(int cmd, caddr_t data);
-
- switch (cmd) {
-
- case SIOCGIFCONF:
- case OSIOCGIFCONF:
- return (ifconf(cmd, data));
-
- #if INET && NETHER > 0
- case SIOCSARP:
- case SIOCDARP:
- #ifndef AMITCP /* no protection on AmigaOS */
- if (error = suser(p->p_ucred, &p->p_acflag))
- return (error);
- /* FALL THROUGH */
- #else
- case SIOCGARPT:
- #endif /* AMITCP */
- case SIOCGARP:
- case OSIOCGARP:
- return (arpioctl(cmd, data));
- #endif
- }
- ifr = (struct ifreq *)data;
- ifp = ifunit(ifr->ifr_name);
- if (ifp == 0)
- return (ENXIO);
- switch (cmd) {
-
- case SIOCGIFFLAGS:
- ifr->ifr_flags = ifp->if_flags;
- break;
-
- case SIOCGIFMETRIC:
- ifr->ifr_metric = ifp->if_metric;
- break;
-
- case SIOCSIFFLAGS:
- #ifndef AMITCP /* no protection on AmigaOS */
- if (error = suser(p->p_ucred, &p->p_acflag))
- return (error);
- #endif /* AMITCP */
- /* if_down() is kludged for Sana-II driver ioctl */
- if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
- spl_t s = splimp();
- if_down(ifp);
- splx(s);
- }
- ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
- (ifr->ifr_flags &~ IFF_CANTCHANGE);
- if (ifp->if_ioctl)
- (void) (*ifp->if_ioctl)(ifp, cmd, data);
- break;
-
- case SIOCSIFMETRIC:
- #ifndef AMITCP /* no protection on AmigaOS */
- if (error = suser(p->p_ucred, &p->p_acflag))
- return (error);
- #endif /* AMITCP */
- ifp->if_metric = ifr->ifr_metric;
- break;
-
- default:
- if (so->so_proto == 0)
- return (EOPNOTSUPP);
- #ifndef COMPAT_43
- return ((*so->so_proto->pr_usrreq)(so,
- PRU_CONTROL,
- (struct mbuf *)cmd,
- (struct mbuf *)data,
- (struct mbuf *)ifp));
- #else
- {
- int ocmd = cmd;
-
- switch (cmd) {
-
- case SIOCSIFDSTADDR:
- case SIOCSIFADDR:
- case SIOCSIFBRDADDR:
- case SIOCSIFNETMASK:
- #if BYTE_ORDER != BIG_ENDIAN
- if (ifr->ifr_addr.sa_family == 0 &&
- ifr->ifr_addr.sa_len < 16) {
- ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
- ifr->ifr_addr.sa_len = 16;
- }
- #else
- if (ifr->ifr_addr.sa_len == 0)
- ifr->ifr_addr.sa_len = 16;
- #endif
- break;
-
- case OSIOCGIFADDR:
- cmd = SIOCGIFADDR;
- break;
-
- case OSIOCGIFDSTADDR:
- cmd = SIOCGIFDSTADDR;
- break;
-
- case OSIOCGIFBRDADDR:
- cmd = SIOCGIFBRDADDR;
- break;
-
- case OSIOCGIFNETMASK:
- cmd = SIOCGIFNETMASK;
- }
- error = ((*so->so_proto->pr_usrreq)(so,
- PRU_CONTROL,
- (struct mbuf *)cmd,
- (struct mbuf *)data,
- (struct mbuf *)ifp));
- switch (ocmd) {
-
- case OSIOCGIFADDR:
- case OSIOCGIFDSTADDR:
- case OSIOCGIFBRDADDR:
- case OSIOCGIFNETMASK:
- *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
- }
- return (error);
-
- }
- #endif
- }
- return (0);
- }
-
- /*
- * Return interface configuration
- * of system. List may be used
- * in later ioctl's (above) to get
- * other information.
- */
- int
- ifconf(cmd, data)
- int cmd;
- caddr_t data;
- {
- register struct ifconf *ifc = (struct ifconf *)data;
- register struct ifnet *ifp = ifnet;
- register struct ifaddr *ifa;
- register char *cp, *ep;
- struct ifreq ifr, *ifrp;
- int space = ifc->ifc_len, error = 0;
-
- ifrp = ifc->ifc_req;
- #ifndef AMITCP
- ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
- #endif
- for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
- #ifdef AMITCP
- ep = sprint_d(ifp->if_unit, ifr.ifr_name, sizeof(ifr.ifr_name));
- *--ep = '/';
- /* Copy the interface name into ifr */
- bcopy(ifp->if_name, ifr.ifr_name, ep - ifr.ifr_name);
- /* Find the end of interface name */
- for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
- ;
- /* Append unit number to it */
- for (; *cp = *ep; cp++, ep++)
- ;
- #else
- bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
- for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
- ;
- *cp++ = '0' + ifp->if_unit; *cp = '\0';
- #endif
- if ((ifa = ifp->if_addrlist) == 0) {
- aligned_bzero_const((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
- #ifdef AMITCP
- *ifrp = ifr;
- #else
- error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
- if (error)
- break;
- #endif
- space -= sizeof (ifr), ifrp++;
- } else
- for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
- register struct sockaddr *sa = ifa->ifa_addr;
- #ifdef COMPAT_43
- if (cmd == OSIOCGIFCONF) {
- struct osockaddr *osa =
- (struct osockaddr *)&ifr.ifr_addr;
- ifr.ifr_addr = *sa;
- osa->sa_family = sa->sa_family;
- error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
- sizeof (ifr));
- ifrp++;
- } else
- #endif
- if (sa->sa_len <= sizeof(*sa)) {
- ifr.ifr_addr = *sa;
- #ifdef AMITCP
- *ifrp = ifr;
- #else
- error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
- sizeof (ifr));
- #endif
- ifrp++;
- } else {
- space -= sa->sa_len - sizeof(*sa);
- if (space < sizeof (ifr))
- break;
- #ifdef AMITCP
- aligned_bcopy_const((caddr_t)&ifr,
- (caddr_t)ifrp,
- sizeof (ifr.ifr_name));
- aligned_bcopy((caddr_t)sa,
- (caddr_t)&ifrp->ifr_addr, sa->sa_len);
- #else
- error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
- sizeof (ifr.ifr_name));
- if (error == 0)
- error = copyout((caddr_t)sa,
- (caddr_t)&ifrp->ifr_addr, sa->sa_len);
- #endif
- ifrp = (struct ifreq *)
- (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
- }
- #ifndef AMITCP
- if (error)
- break;
- #endif
- space -= sizeof (ifr);
- }
- }
- ifc->ifc_len -= space;
- return (error);
- }
-
- static char *
- sprint_d(n, buf, buflen)
- u_int n;
- char *buf;
- int buflen;
- {
- register char *cp = buf + buflen - 1;
-
- *cp = 0;
- do {
- cp--;
- *cp = "0123456789"[n % 10];
- n /= 10;
- } while (n != 0);
- return (cp);
- }
-